#include "Management.h"

Management::Management()
{
}

Management::~Management()
{
}

void Management::link(DataStore* i)
{
    ds = i;
}

void Management::createClient()
{
    accountStruct temp;
    temp.type = Client;

    srand(time(NULL));
    int generate;
    bool isValid = false;
    do
    {
        generate = rand() % 999 + 1;
        if (!ds->findUserID(generate))
        {
            isValid = true;
            temp.ID = generate;
        }
    }
    while (isValid == false);

    cout << "Current client list:" << endl << endl;
    listClients();
    try
    {
        string userInput;
        cout << "New client's username: ";
        userInput.clear();
        getline(cin, userInput, '\n');
        if (ds->hasColon(userInput)) throw 1;
        if (ds->findUserName(userInput)) throw 2;
        temp.user = userInput;

        cout << "New client's password: ";
        userInput.clear();
        getline(cin, userInput, '\n');
        if (ds->hasColon(userInput)) throw 1;
        temp.pass = userInput;

        ds->accounts.push_back(temp);
        cout << endl << "Client successfully created." << endl;
    }
    catch (int e)
    {
        if (e == 2)
            cout << "Username already exists. Exiting." << endl;
        else
            cout << "Colon detected in input. Data has been discarded." << endl;
    }
}

void Management::editClient()
{
    cout << "Current client list:" << endl << endl;
    listClients();
    try
    {
        string userInput;
        cout << "Enter the username of the client you wish to edit: ";
        userInput.clear();
        getline(cin, userInput, '\n');
        if (!ds->findUserName(userInput)) throw 2;

        int indexNo = ds->findUserName(userInput) - 1;
        int input;
        bool hasExit = false;
        do
        {
            cout << endl << "What do you wish to edit?" << endl << endl
                    << "1. Username" << endl
                    << "2. Password" << endl
                    << "Enter an option (3 to stop editing): ";
            cin >> input;
            cin.clear();
            cin.ignore(INT_MAX, '\n');
            switch (input)
            {
            case 1: cout << endl << "Enter new username: ";
                userInput.clear();
                getline(cin, userInput, '\n');
                if (ds->hasColon(userInput)) throw 1;
                if (ds->findUserName(userInput)) throw 3;
                ds->accounts[indexNo].user = userInput;
                cout << "Username modified." << endl;
                break;

            case 2: cout << endl << "Enter new password: ";
                userInput.clear();
                getline(cin, userInput, '\n');
                if (ds->hasColon(userInput)) throw 1;
                ds->accounts[indexNo].pass = userInput;
                cout << "Password modified." << endl;
                break;

            case 3: hasExit = true;
                break;
            default: break;
            }
        }
        while (hasExit == false);
    }
    catch (int e)
    {
        if (e == 3)
            cout << "Username already exists! Exiting." << endl;
        else if (e == 2)
            cout << "Invalid username. Exiting." << endl;
        else
            cout << "Colon detected in input. Editing has been halted." << endl;
    }
}

void Management::deleteClient()
{
    cout << "Current client list:" << endl << endl;
    listClients();

    string userInput;
    cout << "Enter the username of the client you wish to delete: ";
    userInput.clear();
    getline(cin, userInput, '\n');

    if (!ds->findUserName(userInput))
        cout << endl << "Username not found." << endl;
    else
    {
        int indexNo = ds->findUserName(userInput) - 1;
        ds->removeUser(indexNo);
        cout << endl << "Client has been deleted." << endl;
    }
}

void Management::createStaff()
{
    accountStruct temp;
    temp.ID = 0;

    cout << "Current staff list:" << endl << endl;
    listStaff();
    try
    {
        string userInput;
        cout << "New staff's username: ";
        userInput.clear();
        getline(cin, userInput, '\n');
        if (ds->hasColon(userInput)) throw 1;
        if (ds->findUserName(userInput)) throw 2;
        temp.user = userInput;

        cout << "New staff's password: ";
        userInput.clear();
        getline(cin, userInput, '\n');
        if (ds->hasColon(userInput)) throw 1;
        temp.pass = userInput;

        cout << endl << "Pick a type for the new staff member: " << endl << endl
                << "1. Booking Staff" << endl
                << "2. Finance Staff" << endl
                << "3. Holiday Manager" << endl
                << "4. General Manager" << endl
                << "Enter an option: ";
        int input;
        cin >> input;
        cin.clear();
        cin.ignore(INT_MAX, '\n');
        if (input < 1 || input > 4) throw 3;
        temp.type = (accountType) input;

        if (temp.type == HolidayM)
        {
            int generate = 1000;
            bool isValid = false;
            while (isValid == false)
            {
                if (ds->findUserID(generate))
                    generate++;
                else
                    isValid = true;
            }
            temp.ID = generate;
        }

        ds->accounts.push_back(temp);
        cout << endl << ds->accountString(temp.type) << " successfully created." << endl;
    }
    catch (int e)
    {
        if (e == 3)
            cout << "Invalid type picked. Exiting." << endl;
        else if (e == 2)
            cout << "Username already exists. Exiting." << endl;
        else
            cout << "Colon detected in input. Data has been discarded." << endl;
    }
}

void Management::editStaff()
{
    cout << "Current staff list:" << endl << endl;
    listStaff();
    try
    {
        string userInput;
        cout << "Enter the username of the staff you wish to edit: ";
        userInput.clear();
        getline(cin, userInput, '\n');
        if (!ds->findUserName(userInput)) throw 2;

        int indexNo = ds->findUserName(userInput) - 1;
        bool hasExit = false;
        do
        {
            cout << endl << "What do you wish to edit?" << endl << endl
                    << "1. Username" << endl
                    << "2. Password" << endl
                    << "3. Change Type" << endl
                    << "Enter an option (4 to stop editing): ";

            int input;
            cin >> input;
            cin.clear();
            cin.ignore(INT_MAX, '\n');

            switch (input)
            {
            case 1: cout << endl << "Enter new username: ";
                userInput.clear();
                getline(cin, userInput, '\n');
                if (ds->hasColon(userInput)) throw 1;
                if (ds->findUserName(userInput)) throw 3;
                ds->accounts[indexNo].user = userInput;
                cout << "Username modified." << endl;
                break;

            case 2: cout << endl << "Enter new password: ";
                userInput.clear();
                getline(cin, userInput, '\n');
                if (ds->hasColon(userInput)) throw 1;
                ds->accounts[indexNo].pass = userInput;
                cout << "Password modified." << endl;
                break;

            case 3:
            {
                cout << endl << "Pick a new type of staff member: " << endl << endl
                        << "1. Booking Staff" << endl
                        << "2. Finance Staff" << endl
                        << "3. Holiday Manager" << endl
                        << "4. General Manager" << endl
                        << "Enter an option: ";
                int option;
                cin >> option;
                cin.clear();
                cin.ignore(INT_MAX, '\n');
                if (option < 1 || option > 4) throw 4;
                if (ds->accounts[indexNo].type == HolidayM)
                    ds->accounts[indexNo].ID = 0;
                ds->accounts[indexNo].type = (accountType) option;

                if (ds->accounts[indexNo].type == HolidayM)
                {
                    int generate = 1000;
                    bool isValid = false;
                    while (isValid == false)
                    {
                        if (ds->findUserID(generate))
                            generate++;
                        else
                            isValid = true;
                    }
                    ds->accounts[indexNo].ID = generate;
                }
                break;
            }

            case 4: hasExit = true;
                break;
            default: break;
            }
        }
        while (hasExit == false);
    }
    catch (int e)
    {
        if (e == 4)
            cout << "Invalid type picked. Exiting." << endl;
        else if (e == 3)
            cout << "Username already exists! Exiting." << endl;
        else if (e == 2)
            cout << "Invalid username. Exiting." << endl;
        else
            cout << "Colon detected in input. Editing has been halted." << endl;
    }
}

void Management::deleteStaff()
{
    cout << "Current staff list:" << endl << endl;
    listStaff();

    string userInput;
    cout << "Enter the username of the staff you wish to delete: ";
    userInput.clear();
    getline(cin, userInput, '\n');

    if (!ds->findUserName(userInput))
        cout << endl << "Username not found." << endl;
    else
    {
        int indexNo = ds->findUserName(userInput) - 1;
        ds->removeUser(indexNo);
        cout << endl << "Staff member has been deleted." << endl;
    }
}

void Management::listClients()
{
    int size = ds->accounts.size();
    for (int i = 0; i < size; i++)
    {
        if (ds->accounts[i].type == Client)
        {
            cout << "User Name: " << ds->accounts[i].user << endl;
            cout << "Password: " << ds->accounts[i].pass << endl;
            cout << "Customer's ID: " << ds->accounts[i].ID << endl << endl;
        }
    }
}

void Management::listStaff()
{
    int size = ds->accounts.size();
    for (int i = 0; i < size; i++)
    {
        if (ds->accounts[i].type != Client)
        {
            cout << "User Name: " << ds->accounts[i].user << endl;
            cout << "Password: " << ds->accounts[i].pass << endl;
            cout << "Account Type: " << ds->accountString(ds->accounts[i].type) << endl;
            if (ds->accounts[i].type == HolidayM)
                cout << "Holiday Manager's ID: " << ds->accounts[i].ID << endl;
            cout << endl;
        }
    }
}